home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / tos / gnumake / pdmake.zoo / make.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-09-25  |  11.0 KB  |  525 lines

  1.     /***************************************************************\
  2.     *                                *
  3.     *  PDMAKE, Atari ST version                    *
  4.     *                                *
  5.     *  Adapted from mod.sources Vol 7 Issue 71, 1986-12-03.        *
  6.     *                                *
  7.     *  This port makes extensive use of the original net.sources    *
  8.     *  port by Jwahar Bammi.                    *
  9.     *                                *
  10.     *      Ton van Overbeek                        *
  11.     *      Email: TPC862@ESTEC.BITNET                *
  12.     *             TPC862%ESTEC.BITNET@WISCVM.WISC.EDU    (ARPA)    *
  13.     *             ...!mcvax!tpc862%estec.bitnet   (UUCP Europe)    *
  14.     *             ...!ucbvax!tpc862%estec.bitnet  (UUCP U.S.A.)    *
  15.     *             71450,3537  (CompuServe)                *
  16.     *                                *
  17.     \***************************************************************/
  18.  
  19. /*
  20.  *    Do the actual making for make
  21.  */
  22.  
  23. #include <stdio.h>
  24.  
  25. #ifdef unix
  26. #include <sys/types.h>
  27. #include <sys/stat.h>
  28. #include <sys/errno.h>
  29. #endif
  30. #ifdef eon
  31. #include <sys/stat.h>
  32. #include <sys/err.h>
  33. #endif
  34. #ifdef os9
  35. #include <time.h>
  36. #include <os9.h>
  37. #include <modes.h>
  38. #include <direct.h>
  39. #include <errno.h>
  40. #endif
  41.  
  42. #include "h.h"
  43. #ifdef ATARIST
  44. #include "astat.h"
  45. #define time Time
  46. #endif
  47.  
  48. /*
  49.  *    Exec a shell that returns exit status correctly (/bin/esh).
  50.  *    The standard EON shell returns the process number of the last
  51.  *    async command, used by the debugger (ugg).
  52.  *    [exec on eon is like a fork+exec on unix]
  53.  */
  54. int
  55. dosh(string, shell)
  56. char *    string;
  57. char *    shell;
  58. {
  59.     int    number;
  60.  
  61. #ifdef unix
  62.     return system(string);
  63. #endif
  64. #ifdef ATARIST
  65.     return system(string);
  66. #endif
  67. #ifdef eon
  68.     return ((number = execl(shell, shell,"-c", string, 0)) == -1) ?
  69.         -1:    /* couldn't start the shell */
  70.         wait(number);    /* return its exit status */
  71. #endif
  72. #ifdef os9
  73.     int    status, pid;
  74.  
  75.     strcat(string, "\n");
  76.     if ((number = os9fork(shell, strlen(string), string, 0, 0, 0)) == -1)
  77.         return -1;        /* Couldn't start a shell */
  78.     do
  79.     {
  80.         if ((pid = wait(&status)) == -1)
  81.             return -1;    /* child already died!?!? */
  82.     } while (pid != number);
  83.  
  84.     return status;
  85. #endif
  86. }
  87.  
  88.  
  89. /*
  90.  *    Do commands to make a target
  91.  */
  92. void
  93. docmds1(np, lp)
  94. struct name *        np;
  95. struct line *        lp;
  96. {
  97.     bool            ssilent;
  98.     bool            signore;
  99.     int            estat;
  100.     register char *        q;
  101.     register char *        p;
  102.     char *            shell;
  103.     register struct cmd *    cp;
  104.  
  105.  
  106.     if (*(shell = getmacro("SHELL")) == '\0')
  107. #ifdef eon
  108.         shell = ":bin/esh";
  109. #endif
  110. #ifdef unix
  111.         shell = "/bin/sh";
  112. #endif
  113. #ifdef os9
  114.         shell = "shell";
  115. #endif
  116.  
  117.     for (cp = lp->l_cmd; cp; cp = cp->c_next)
  118.     {
  119.         strcpy(str1, cp->c_cmd);
  120.         expand(str1);
  121.         q = str1;
  122.         ssilent = silent;
  123.         signore = ignore;
  124.         while ((*q == '@') || (*q == '-'))
  125.         {
  126.             if (*q == '@')       /*  Specific silent  */
  127.                 ssilent = TRUE;
  128.             else           /*  Specific ignore  */
  129.                 signore = TRUE;
  130.             q++;           /*  Not part of the command  */
  131.         }
  132.  
  133.         if (!domake)
  134.             ssilent = 0;
  135.  
  136.         if (!ssilent)
  137.             fputs("    ", stdout);
  138.  
  139.         for (p=q; *p; p++)
  140.         {
  141.             if (*p == '\n' && p[1] != '\0')
  142.             {
  143.                 *p = ' ';
  144.                 if (!ssilent)
  145.                     fputs("\\\n", stdout);
  146.             }
  147.             else if (!ssilent)
  148.                 putchar(*p);
  149.         }
  150.         if (!ssilent)
  151.             putchar('\n');
  152.  
  153.         if (domake)
  154.         {            /*  Get the shell to execute it  */
  155.             if ((estat = dosh(q, shell)) != 0)
  156.             {
  157.                 if (estat == -1)
  158. #ifdef ATARIST
  159.                     fatal("Couldn't execute %s", q);
  160. #else
  161.                     fatal("Couldn't execute %s", shell);
  162. #endif
  163.                 else
  164.                 {
  165.                     printf("%s: Error code %d", myname, estat);
  166.                     if (signore)
  167.                         fputs(" (Ignored)\n", stdout);
  168.                     else
  169.                     {
  170.                         putchar('\n');
  171.                         if (!(np->n_flag & N_PREC))
  172.                             if (unlink(np->n_name) == 0)
  173.                                 printf("%s: '%s' removed.\n", myname,
  174.                                        np->n_name);
  175.                         exit(estat);
  176.                     }
  177.                 }
  178.             }
  179.         }
  180.     }
  181. }
  182.  
  183.  
  184. docmds(np)
  185. struct name *    np;
  186. {
  187.     register struct line *    lp;
  188.  
  189.  
  190.     for (lp = np->n_line; lp; lp = lp->l_next)
  191.         docmds1(np, lp);
  192. }
  193.  
  194.  
  195. #ifdef os9
  196. /*
  197.  *    Some stuffing around to get the modified time of a file
  198.  *    in an os9 file system
  199.  */
  200. getmdate(fd, tbp)
  201. struct sgtbuf *        tbp;
  202. {
  203.     struct registers    regs;
  204.     static struct fildes    fdbuf;
  205.  
  206.  
  207.     regs.rg_a = fd;
  208.     regs.rg_b = SS_FD;
  209.     regs.rg_x = &fdbuf;
  210.     regs.rg_y = sizeof (fdbuf);
  211.  
  212.     if (_os9(I_GETSTT, ®s) == -1)
  213.     {
  214.         errno = regs.rg_b & 0xff;
  215.         return -1;
  216.     }
  217.     if (tbp)
  218.     {
  219.         _strass(tbp, fdbuf.fd_date, sizeof (fdbuf.fd_date));
  220.         tbp->t_second = 0;    /* Files are only acurate to mins */
  221.     }
  222.     return 0;
  223. }
  224.  
  225.  
  226. /*
  227.  *    Kludge routine to return an aproximation of how many
  228.  *    seconds since 1980.  Dates will be in order, but will not
  229.  *    be lineer
  230.  */
  231. time_t
  232. cnvtime(tbp)
  233. struct sgtbuf        *tbp;
  234. {
  235.     long            acc;
  236.  
  237.  
  238.     acc = tbp->t_year - 80;        /* Baseyear is 1980 */
  239.     acc = acc * 12 + tbp->t_month;
  240.     acc = acc * 31 + tbp->t_day;
  241.     acc = acc * 24 + tbp->t_hour;
  242.     acc = acc * 60 + tbp->t_minute;
  243.     acc = acc * 60 + tbp->t_second;
  244.  
  245.     return acc;
  246. }
  247.  
  248.  
  249. /*
  250.  *    Get the current time in the internal format
  251.  */
  252. time(tp)
  253. time_t *        tp;
  254. {
  255.     struct sgtbuf        tbuf;
  256.  
  257.  
  258.     if (getime(&tbuf) < 0)
  259.         return -1;
  260.  
  261.     if (tp)
  262.         *tp = cnvtime(&tbuf);
  263.  
  264.     return 0;
  265. }
  266. #endif
  267.  
  268. #ifdef ATARIST
  269. /*
  270.  *    Get the current time in the internal format
  271.  */
  272. time(tp)
  273. time_t *        tp;
  274. {
  275.     if (tp)
  276.         *tp = Gettime();
  277.  
  278.     return 0;
  279. }
  280. #endif
  281.  
  282. /*
  283.  *    Get the modification time of a file.  If the first
  284.  *    doesn't exist, it's modtime is set to 0.
  285.  */
  286. void
  287. modtime(np)
  288. struct name *    np;
  289. {
  290. #ifdef unix
  291.     struct stat        info;
  292.     int            fd;
  293.  
  294.  
  295.     if (stat(np->n_name, &info) < 0)
  296.     {
  297.         if (errno != ENOENT)
  298.             fatal("Can't open %s; error %d", np->n_name, errno);
  299.  
  300.         np->n_time = 0L;
  301.     }
  302.     else
  303.         np->n_time = info.st_mtime;
  304. #endif
  305. #ifdef eon
  306.     struct stat        info;
  307.     int            fd;
  308.  
  309.  
  310.     if ((fd = open(np->n_name, 0)) < 0)
  311.     {
  312.         if (errno != ER_NOTF)
  313.             fatal("Can't open %s; error %02x", np->n_name, errno);
  314.  
  315.         np->n_time = 0L;
  316.     }
  317.     else if (getstat(fd, &info) < 0)
  318.         fatal("Can't getstat %s; error %02x", np->n_name, errno);
  319.     else
  320.         np->n_time = info.st_mod;
  321.  
  322.     close(fd);
  323. #endif
  324. #ifdef os9
  325.     struct sgtbuf    info;
  326.     int            fd;
  327.  
  328.  
  329.     if ((fd = open(np->n_name, 0)) < 0)
  330.     {
  331.         if (errno != E_PNNF)
  332.             fatal("Can't open %s; error %02x", np->n_name, errno);
  333.  
  334.         np->n_time = 0L;
  335.     }
  336.     else if (getmdate(fd, &info) < 0)
  337.         fatal("Can't getstat %s; error %02x", np->n_name, errno);
  338.     else
  339.         np->n_time = cnvtime(&info);
  340.  
  341.     close(fd);
  342. #endif
  343. #ifdef ATARIST
  344.     struct stat        info;
  345.     extern int        getstat();        /*  in ststuff.c  */
  346.     extern void        FlipWords();        /*  in ststuff.c  */
  347.  
  348.     if (getstat(np->n_name, &info) < 0)
  349.         np->n_time = 0L;
  350.     else
  351.     {
  352.         FlipWords(&info.st_mod);
  353.         np->n_time = info.st_mod;
  354.     }
  355. #endif
  356. }
  357.  
  358.  
  359. /*
  360.  *    Update the mod time of a file to now.
  361.  */
  362. void
  363. touch(np)
  364. struct name *    np;
  365. {
  366.     char    c;
  367.     int        fd;
  368.  
  369.  
  370.     if (!domake || !silent)
  371.         printf("    touch(%s)\n", np->n_name);
  372.  
  373.     if (domake)
  374.     {
  375. #ifdef unix
  376.         long    a[2];
  377.  
  378.         a[0] = a[1] = time(0);
  379.         if (utime(np->n_name, &a[0]) < 0)
  380.             printf("%s: '%s' not touched - non-existant\n",
  381.                     myname, np->n_name);
  382. #endif
  383. #ifdef eon
  384.         if ((fd = open(np->n_name, 0)) < 0)
  385.             printf("%s: '%s' not touched - non-existant\n",
  386.                     myname, np->n_name);
  387.         else
  388.         {
  389.             uread(fd, &c, 1, 0);
  390.             uwrite(fd, &c, 1);
  391.         }
  392.         close(fd);
  393. #endif
  394. #ifdef os9
  395.         /*
  396.          *    Strange that something almost as totally useless
  397.          *    as this is easy to do in os9!
  398.          */
  399.         if ((fd = open(np->n_name, S_IWRITE)) < 0)
  400.             printf("%s: '%s' not touched - non-existant\n",
  401.                     myname, np->n_name);
  402.         close(fd);
  403. #endif
  404. #ifdef ATARIST
  405.         if ((fd = Fopen(np->n_name, 0)) < 0)
  406.             printf("%s: '%s' not touched - non-existant\n",
  407.                     myname, np->n_name);
  408.         else
  409.         {
  410.             long tim;
  411.  
  412.             tim = Gettime();
  413.             FlipWords(&tim);
  414.             if (Fdatime( &tim, fd, 1) < 0)
  415.                 printf("%s: '%s' not touched - disk protected ?\n",
  416.                         myname, np->n_name);
  417.             Fclose(fd);
  418.         }
  419. #endif
  420.     }
  421. }
  422.  
  423.  
  424. /*
  425.  *    Recursive routine to make a target.
  426.  */
  427. int
  428. make(np, level)
  429. struct name *    np;
  430. int        level;
  431. {
  432.     register struct depend *    dp;
  433.     register struct line *    lp;
  434.     register struct depend *    qdp;
  435.     time_t            dtime = 1;
  436.     bool            didsomething = 0;
  437.  
  438.  
  439.     if (np->n_flag & N_DONE)
  440.         return 0;
  441.  
  442.     if (!np->n_time)
  443.         modtime(np);            /*  Gets modtime of this file  */
  444.  
  445.     if (rules)
  446.     {
  447.         for (lp = np->n_line; lp; lp = lp->l_next)
  448.             if (lp->l_cmd)
  449.                 break;
  450.         if (!lp)
  451.             dyndep(np);
  452.     }
  453.  
  454.     if (!(np->n_flag & N_TARG) && np->n_time == 0L)
  455.         fatal("Don't know how to make %s", np->n_name);
  456.  
  457.     for (qdp = (struct depend *)0, lp = np->n_line; lp; lp = lp->l_next)
  458.     {
  459.         for (dp = lp->l_dep; dp; dp = dp->d_next)
  460.         {
  461.             make(dp->d_name, level+1);
  462.             if (np->n_time < dp->d_name->n_time)
  463.                 qdp = newdep(dp->d_name, qdp);
  464.             dtime = max(dtime, dp->d_name->n_time);
  465.         }
  466.         if (!quest && (np->n_flag & N_DOUBLE) && (np->n_time < dtime))
  467.         {
  468.             make1(np, lp, qdp);            /* free()'s qdp */
  469.             dtime = 1;
  470.             qdp = (struct depend *)0;
  471.             didsomething++;
  472.         }
  473.     }
  474.  
  475.     np->n_flag |= N_DONE;
  476.  
  477.     if (quest)
  478.     {
  479.         long        t;
  480.  
  481.         t = np->n_time;
  482.         time(&np->n_time);
  483.         return t < dtime;
  484.     }
  485.     else if (np->n_time < dtime && !(np->n_flag & N_DOUBLE))
  486.     {
  487.         make1(np, (struct line *)0, qdp);    /* free()'s qdp */
  488.         time(&np->n_time);
  489.     }
  490.     else if (level == 0 && !didsomething)
  491.         printf("%s: '%s' is up to date\n", myname, np->n_name);
  492.     return 0;
  493. }
  494.  
  495.  
  496. make1(np, lp, qdp)
  497. register struct depend *    qdp;
  498. struct line *    lp;
  499. struct name *    np;
  500. {
  501.     register struct depend *    dp;
  502.  
  503.  
  504.     if (dotouch)
  505.         touch(np);
  506.     else
  507.     {
  508.         strcpy(str1, "");
  509.         for (dp = qdp; dp; dp = qdp)
  510.         {
  511.             if (strlen(str1))
  512.                 strcat(str1, " ");
  513.             strcat(str1, dp->d_name->n_name);
  514.             qdp = dp->d_next;
  515.             free(dp);
  516.         }
  517.         setmacro("?", str1);
  518.         setmacro("@", np->n_name);
  519.         if (lp)                    /* lp set if doing a :: rule */
  520.             docmds1(np, lp);
  521.         else
  522.             docmds(np);
  523.     }
  524. }
  525.